/*!
 * TinyTable v0.0.9
 */
/**
 * 
 * ###0.0.2 update### 
 * - use <table> to replace <ul> as basic structure
 * - add URL parameters  
 * - cancel dataList function -- now replaced as dataTable
 * - add selected callback
 * - add paging-function 
 * - rename to tiny-table
 * 
 * ###0.0.3### 
 * - add event-aspect -- allow user to custom action 
 * - add control bar
 *
 * #### 0.0.4###
 * - re-factor pagination
 * 
 * ### 0.0.6 ### 
 * - fix bug: refresh cannot normally add control bar
 * - add caption as title 
 * - re-factor control bar (using Font-Awesome)
 * 
 * ### 0.0.7 ### 
 * - add data cache system -- Something like view-model named 'cache' 
 *			added to tinytable representing the current page data (JSON).
 * - add METHOD addRow 
 *	-- $tinytable( 'addRow', rowData[], callback($tr,row));
 * 
 * - add METHOD delRow
 *  -- $tinytable( 'delRow', key [default col[0]] OR,callBack($tr,row));
 *
 * - add METHOD sync 
 *	-- $tinytable( 'sync', callback(addRows,delRows));
 * 
 * - add METHOD get cache;
 *  -- $tinytable( 'data');
 * 
 * 
 * ### 0.0.8 ###
 * - add editable mode 
 *
 * ### 0.0.9 ###
 * 0.add custom sort
 *  $.tinytable('sort',[/sort params/]...); 
 * 1.add custom search
 *  $.tinytable('search'{/search params/}); -- //todo??;
 */

(function($, undefined) {

	;;
	
	var defaults = {
		/* dataList:[] */
		title : 'tinytable',
		classes : 'jquery-tinytable',
		url : '', /* json */
		params : {}, /* get params */
		pgLens : [ 5, 10, 20 ], /* page length*/

		class_sort_desc : 'fa fa-sort-desc',
        class_sort_asc : 'fa fa-sort-asc',
        class_sortable : 'sortable',
		
		/* Interactive_Lable AS IL*/
		IL_records_location : 'rows',
		IL_pg_cnt : 'total',
		IL_pg_len : 'rows',
		IL_pg_idx : 'page',
		IL_records_size : 'records',
		

		IL_sort_order : 'sort' ,
		IL_sort_idx : 'sidx' ,

		/*SEARCH*/
		IL_search_headers : '',
		
		filters:'',

		allowAdd : true,
		allowNav : true,
		allowCtrl : true,
		allowHead : true,
		
		selectMode : 'none',
		selected : function() {
		},
		unselected : function() {
		}, /* 只在多选时可用 */

		nav : {
			/* 导航条文字 */
			firstLabel : 'Home Page',
			lastLabel : 'Last Page',
			prevLabel : 'Prev.',
			nextLabel : 'Next'
		},
		on : {
			load : function(){}
		},
		ctrl : {
			refresh : {
				allow :true,
				view : '<i class="fa fa-refresh"></i>',
				func : function(table) {
					table.refresh();
				}
			},
			add : {
				allow:false,
				view :'<i class="fa fa-plus"></i>',
				func : function(table) {
					table.addRow({});
				}
			}
		}, // TODO default control buttons

		_notEmpty : function(data) {
			return !!(typeof(data)==='number' || ( data && data !== 'null'));
		},

		emptyRowFill : '<a>(empty)</a>',
		emptyFill : '',

		navSize : 5,
		colModel : [],
		_id : '_id' /* TODO???? hidden column mode not used yet*/

	}
	;;
	
	var __colModel_example__ = {
		id : 'default', /* required */
		key : false, /* optional key of this row */
		name : 'default', /* display name */
		classes : 'class1 class2',
		edit : {
			allow : false,
			/*register event*/
			trigger : function($td,render){
				$td.bind('click',function(){
					render();
				});
			},
			//TODO ulgy
			renderer : function($td,row,name,data,recover) {
				var $input = $('<input type="text" >')
					.css('width',(parseInt($td.css('width'))*1 + 20)+'px')
					.attr('name', name)
					.bind('blur', function(){
							data($(this).val());
							recover();
						})
					.val(data());
				$td.append($input);
				$input.focus();
			}
		},
		on : {},
		renderer : function($td, row, data) {
			$td.text(data);
			$td.attr('title', data);
		},
		sort: false /* sort-allow flag*/
	};

	var tl = $.tinytable = {
		auther : 'edwinyxc',
		email : 'edwinyxc@gmail.com',
		version : "0.0.6-x86-win32-beta-m1",
		require : 'IE 8.0+, FF 25.0+, CHROME 31.0+, jquery 1.7.2+, font-awesome 1.4+',
		remark : ''
	};

		 
	 
	var __search_example__ = {
		//TODO ????
	};
	
	var __sort_example__ = {
		id:'vid_example', /*required*/
		sort:'asc' /*desc OR asc by default*/
	};

	$.fn.tinytable = function(options) {

		// method calling
		if (typeof options == 'string') {
			var args = Array.prototype.slice.call(arguments, 1);
			var res = undefined;
			this.each(function() {
				var tinyList = $.data(this, 'tinytable');
				if (tinyList && $.isFunction(tinyList[options])) {
					// console.log(tinyList[options].toString());
					var r = tinyList[options].apply(tinyList, args);
					if (res === undefined) {
						res = r;
					}
					if (options == 'destroy') {
						$.removeData(this, 'tinytable');
					}
				}
			});
			if (res !== undefined) {
				return res;
			}
			return this;
		}

		$this = $(this);
		this.each(function(i, _element) {
			var element = $(_element);

			;
			var table = new TinyTable(element, setDefaults(options));
			element.data('tinytable', table); // TODO: look into memory leak
			// implications
			table.render();
		});

		return this;
	};
	;

	// function for adding/overriding defaults
	function setDefaults(d) {
		return $.extend(true, {}, defaults, d);
	}

	;;

	function TinyTable(div, options) {

		var t = this;
		// exports
		
		t.list = list;
		// add new row
		t.addRow = addRow;
		t.addRows = [];
		t.delRow = delRow;
		t.delRows = [];
		t.sync = sync;
		t.data = data;
		
		t.altRows = [];

		t.options = options;
		t.render = render;
		t.refresh = refreshData;
		// t.on = on;
		t.sel = sel;
		// t.data = refreshData;
		// t.selCol = selCol;
		t.selData = selData;
		// t.unselect = unselect;
		t.destory = destory;
		
		t.sort = sort;
		
		t.selectedRows = function() {
			return _selectedRows;
		};
		// imports
		// locals

		// ??
		var list = [];

		var colModel = (function() {
			for ( var m in options.colModel) {
				var model = options.colModel[m];
				var replacement = $.extend(true, {}, __colModel_example__,
						model);
				options.colModel[m] = replacement;
			}
			return options.colModel;
		})();

		var $container = div;
		var $table = $(
				'<table class = ' + (options.classes ? options.classes : "")
						+ '/>').append($('<caption/>').text(options.title));
		var $thead = $('<thead/>');
		var $tbody = $('<tbody/>');
		var $tfoot = $('<tfoot/>');
		var $nav = $('<div class="page"/>');
		var $control = $('<div class="ctrl"/>');

		var $trs = [];
		var $cells = [];
		var values = [];
		t.cache = [];

		// TODO var xx;

		/**
		 * get key by colModel
		 */
		var _keyId = (function() {
			for ( var c in options.colModel) {
				if (options.colModel[c]['key']) {
					return options.colModel[c].id;
				}
				return options.colModel[0].id;
			}
		})();

		function _putTogether() {
			$container.empty();
			$table.append($thead).append($tbody).append($tfoot);
			$container.append($table);
		}

		function _initFoot() {
			if (options.allowCtrl) {
				$nav.append(_renderCtrl());
			}
			if (options.allowNav)
				$tfoot.append($('<tr/>').append(
						$('<td/>').attr('colspan', _calcFootColSpan()).append(
								$nav)));
		}

		function _renderCtrl() {
			for ( var btn in options.ctrl) {
				var addon = options.ctrl[btn];
				if(addon.allow){
					var callBack = (function(addon) {
						return function() {
							addon.func(t);
						};
					})(addon);
					$control.append($(addon.view).bind('click', callBack));
				}
			}
			return $control;
		}

		function _calcFootColSpan() {
			if (options.selectMode === 'none') {
				return options.colModel.length;
			}
			return options.colModel.length + 1;
		}
		
		function _initSort() {
			return $('<span class = "sort"/>');			
		}

		function _initHead() {
			var _colModel;
			var $tr_h = $('<tr/>');
			var $th;
			for ( var col in colModel) {
				_colModel = colModel[col];
				$th = $("<th/>");
				$th.text(_colModel.name);
				if (_colModel.classes) {
					$th.attr('class', _colModel.classes);
				}
				$th.attr('name', _colModel.name);
				/*sort*/
				if( _colModel.sort ) {
					$th.append('<span class = "sort" ></span>');
					$th.addClass(options.class_sortable);
					var _sort = {sort: 'asc'};
					
					$th.click((function(colModel,holder) {
						return function() {
						
							var $this = $(this);
							if (holder.sort == 'asc'){
								sort(colModel.id, 'asc', function(){	
									$this.find('.sort')
										.removeClass(options.class_sort_asc)
										.addClass(options.class_sort_desc);
								});
								
								holder.sort = 'desc';
							}
							else {
								sort(colModel.id, 'desc', function(){
									$this.find('.sort')
										.removeClass(options.class_sort_desc)
										.addClass(options.class_sort_asc);
								});
								
								holder.sort = 'asc';
							}
							
						};
					})(_colModel,_sort));
				}
				
				$tr_h.append($th);
			}

			if (options.selectMode == 'check') {
				_renderCheckBoxForHead($tr_h);
			} else if (options.selectMode == 'radio') {
				_renderRadioForHead($tr_h);
			}

			$thead.empty();
			$thead.append($tr_h);
		}

		function _renderEmpty() {
			$cells = [];
			values = [];
			$trs = [];
			$tbody.empty();
//			$tbody.append(
//					$('<tr/>').append(
//							$('<td/>').attr('colspan', _calcFootColSpan())
//									.append(options.emptyRowFill))).addClass(
//					'blank');
		}

		function _renderTr(rowData, row) {
			$cells[row] = [];
			values[row] = [];
			var $tr = $('<tr/>');
			$tr.addClass((function(row) {
				if (row % 2 == 0) {
					return 'even';
				}
				return 'odd';
			})(row));
			$tr.addClass('' + row);

			$trs[row] = $tr;

			// render checkbox OR radio OR nothing
			if (options.selectMode == 'check') {
				_renderCheckBoxForCell($tr, rowData);
			}

			else if (options.selectMode == 'radio') {
				_renderRadioForCell($tr, rowData);
				$tr.click(function(){
					$(this).children('td').first().click();
					return false;
				});
			}

			for ( var col = 0; col < colModel.length; col++) {
				var $td = _renderTd(rowData, row, col);
				$cells[row][col] = $td;
				$tr.append($td);
			}
			return $tr;
		}

		function _renderTd(rowData, row, col) {
			var $td = $('<td class='
					+ (colModel.classes ? colModel.classes : "") + '/>');
			$td.attr('row', row);
			$td.attr('col', col);
			var data = eval('(rowData.'+colModel[col].id+')');
			values[row][col] = data;
			if ($.isFunction(colModel[col].renderer)) {
				$td.empty();
				colModel[col].renderer($td, rowData, 
					(options._notEmpty(data) ? data
						: options.emptyFill));
			}
			// if editable
			if (colModel[col].edit.allow) {
				
				var dataFunc = (function(row,name,t){
				
					return function(data){
						var oldVal = eval('row.'+name+'');
						if((typeof data ) === 'undefined'){
							return oldVal;
						}
						if (data != oldVal){
							eval('row.'+name+'="'+data+'";');
							if((	$.inArray(row,t.altRows) === -1) 
									&& ($.inArray(row,t.addRows) === -1)
									&& ($.inArray(row,t.delRows) === -1)
							){
								t.altRows.push(row);
							}
						}
					};
				})(rowData,colModel[col].id,t);
				
				var recover = (function(originalRender,$td,row,name){
				
							return function(){
								//TODO default by recover 
								$td.empty();
								$td.unbind();
								originalRender($td,row,eval('row.'+name+''));
								//TODO?????
								colModel[col].edit.trigger($td,render);
							};
							
						})(colModel[col].renderer,
							$td,rowData,
							colModel[col].id);
						
				//render
				var render = (function($td,row,name,data,recover){
							return function(){
								$td.empty();
								$td.unbind();
								colModel[col].edit.renderer($td,
															row,
															name,
												dataFunc,recover);
							};
						})($td,rowData,
							colModel[col].id,
							dataFunc,recover);
				
				colModel[col].edit.trigger($td, render);
			}
			
			return $td;
		}

		function _renderCells(rows,t) {
			t.cache = rows;
			$cells = [];
			values = [];
			$trs = [];
			$tbody.empty();
			for ( var row = 0; row < rows.length; row++) {
				$tbody.append(_renderTr(rows[row], row));
			}
		}

		function _renderCheckBoxForHead($tr) {
			$tr.find(' selctrl').remove();
			var $th = $('<th/>').addClass('selctrl');
			$i = $('<i/>').addClass('fa').addClass('fa-square-o');
			$th.click(function() {
				if ($(this).attr('checked')) {
					$tbody.find('.selctrl').each(function(i, td) {
						var $td = $(td);
						if ($td.attr('checked')) {
							$td.trigger('click');
						}
					});
					$(this).find('i').removeClass('fa-check-square-o')
							.addClass('fa-square-o');
					$(this).removeAttr('checked');
				} else {
					$tbody.find('.selctrl').each(function(i, td) {
						var $td = $(td);
						if (!$td.attr('checked')) {
							$td.trigger('click');
						}
					});
					$(this).find('i').removeClass('fa-square-o').addClass(
							'fa-check-square-o');
					$(this).attr('checked', 'checked');
				}

			});
			$th.append($i);
			$tr.prepend($th);
		}

		function _renderRadioForHead($tr) {
			$tr.find(' selctrl').remove();
			var $th = $('<th/>').addClass('selctrl');
			$i = $('<i/>');
			$th.append($i);
			$tr.prepend($th);
		}

		function _renderCheckBoxForCell($tr, rowData) {
			$tr.find('selctrl').remove();
			var $td = $('<td/>').addClass('selctrl');

			$td.click(function() {
				var $i = $(this).find('i');
				var checked = $(this).attr('checked');
				var $tr = $(this).parent('tr');

				if (checked) {
					$(this).removeAttr('checked');
					$i.removeClass('fa-check-square-o');
					$i.addClass('fa-square-o');
					$tr.removeClass('sel');
					if ($.isFunction(options.unselected)) {
						options.unselected($tr, rowData);
					}
				} else {
					$(this).attr('checked', 'checked');
					$i.removeClass('fa-square-o');
					$i.addClass('fa-check-square-o');
					$tr.addClass('sel');
					if ($.isFunction(options.selected)) {
						options.selected($tr, rowData);
					}
				}
				return false;
			});

			$i = $('<i/>').addClass('fa').addClass('fa-square-o');
			$i.attr('value', rowData[_keyId]);
			$i.attr('name', _keyId);
			$td.append($i);
			$tr.prepend($td);
		}

		function _renderRadioForCell($tr, rowData) {
			$tr.find('selctrl').remove();
			var $td = $('<td/>').addClass('selctrl');
			$td.click(function() {
				$tbody.find('.fa-check-square-o').removeClass(
						'fa-check-square-o').addClass('fa-square-o');
				$tbody.find('.sel').removeClass('sel');

				var $i = $(this).find('i');
				$i.removeClass('fa-square-o').addClass('fa-check-square-o');
				$tr.addClass('sel');
				if ($.isFunction(options.selected)) {
					options.selected($tr, rowData);
				}
				return false;
			});
			$i = $('<i/>').addClass('fa').addClass('fa-square-o');
			$i.attr('value', rowData[_keyId]);
			$i.attr('name', _keyId);
			$td.append($i);
			$tr.prepend($td);
		}
		
		function _selRow(row) {
			var _id;
			if (typeof row === 'string') {
				_id = parseInt(row);
			} else {
				_id = row;
			}
			if (_id >= $trs.length) {
				return null;
			}
			return $trs[_id];
		}

		function _selCell(row, col) {
			var _row;
			var _col;
			if (typeof row === 'string') {
				_row = parseInt(row);
			} else {
				_row = row;
			}
			if (typeof col === 'string') {
				_col = parseInt(col);
			} else {
				_col = col;
			}
			if (_row >= $list.length || _col >= colModel.length)
				return null;

			return $cells[_row][_col];
		}

		function _selCol(col) {
			var _id;
			if (typeof col === 'string') {
				_id = parseInt(col);
			} else {
				_id = col;
			}
			if (_id >= colModel.length) {
				return null;
			}
			var col = [];
			for ( var i = 0; i < list.length; i++) {
				col[i] = _selCell(i, _id);
			}
			return col;
		}

		function _getIdxOfCol(colId) {
			var i;
			var colModelEntry;
			for (i = 0; i < colModel; i++) {
				colModelEntry = colModel[i];
				if (colModelEntry.id === colId) {
					return i;
				}
			}
			return -1;
		}


		// ------------------------------------- data -------//

		/**
		 * addRow 方法 $.tinytable('addRow',rowData
		 * [object],callBackFun($tr,row));
		 */
		function addRow(row, cb) {
			t.addRows.push(row);
			t.cache.push(row);
			var $tr = _renderTr(row, values.length, true);
			$tbody.append($tr);
			if($.isFunction(cb))
			cb($tr, row);
		}
		
		/**
		 * delRow 方法 $.tinytable('delRow',key [default col[0]]
		 * ||,callBackFun($tr,row));
		 */
		function delRow(key, cb) {
			var search = _findRowByKey(key, t.cache);
			if (!search)
				return false;
				
			t.delRows.push(search.data);
			
			if($.isFunction(cb))
				cb($trs[search.id], search.data);
				
			$trs[search.id].remove();
			delete t.cache[search.id];
		}
		
		function _findRowByKey(key, data) {
			for ( var i in data) {
				if (data[i][_keyId] == key) {
					return {
						data : data[i],
						id : i
					};
				}
			}
			return false;
		}
		
		/**
		 * 添加 sync 方法 $.tinytable(sync,callback(addRows,delRows));
		 */
		function sync(cb) {
			if (!$.isFunction(cb))
				return false;
			cb(t.addRows,t.altRows,t.delRows);
			refreshData();
		}
		
		/**
		 * 4.添加 获取缓存数据方法 $.tinytable(data);
		 */
		function data() {
			return t.cache;
		}

		function refreshData(url, params, cb) {
			// clear cache
			t.addRows = [];
			t.altRows = [];
			t.delRows = [];

			var paramObj = $.extend(true, {}, options.params,
					(typeof params === 'string' ? {} : params));
			// console.log(pgLen);
			if (!options.pgLen) {
				options.pgLen = options.pgLens[0];
			}
			paramObj[options.IL_pg_len] = options.pgLen;
			paramObj[options.IL_pg_idx] = 1;
			var _url = url;

			if (!_url)
				_url = options.url;
			// loading mask TODO
			if (typeof params === 'string') {
				_url += '&';
				_url += params;
			}
			$.post(_url, paramObj,(function(t){
					return function(json) {
						// set data of this table
						
						// loading unmask TODO
						if (!json[options.IL_records_location]
								|| json[options.IL_records_location].length < 1) {
							_renderEmpty();
							return;
						}
						_renderCells(json[options.IL_records_location],t);
						if (options.allowNav) {
							_navBar(json[options.IL_pg_cnt], options.url,
									options.params, function(json) {
										_renderCells(json[options.IL_records_location],t);
									});
						}
						if($.isFunction(options.on.load)){
							options.on.load(t.cache);
						}
						if($.isFunction(cb))
							cb();
					};
			})(t), 'json');
			return div;
		}

		/**
		 * 导航条绘条
		 */
		function _renderNavBar() {
			$nav.empty();

			$sums = $('<b class="index_all"><span class="pgIdx"></span><span class = "pgCnt"></span></b>');

			$first = $('<a/>').append(
					$('<i/>').addClass('fa fa-angle-double-left').attr('title',
							options.nav.firstLabel))
					.addClass('firstPage unava');

			$last = $('<a/>').append(
					$('<i/>').addClass('fa fa-angle-double-right').attr(
							'title', options.nav.lastLabel)).addClass(
					'lastPage unava');

			$prev = $('<a/>').append(
					$('<i/>').addClass('fa fa-angle-left').attr('title',
							options.nav.prevLabel)).addClass('prePage unava');

			$next = $('<a/>').append(
					$('<i/>').addClass('fa fa-angle-right').attr('title',
							options.nav.nextLabel)).addClass('nextPage unava');

			$pgLenSelector = $('<select/>');

			for ( var i in options.pgLens) {
				$pgLenSelector.append('<option>' + options.pgLens[i]
						+ '</option>');
			}

			$pgLenSelector.bind('change', function() {
				options.pgLen = $(this).val();
				refreshData();
			});

			$pages = $('<span/>');
			$pages.addClass('pages');

			$nav.append($first).append($prev).append($pages).append($next)
					.append($last).append($sums).append($pgLenSelector);

		}

		/**
		 * 更新导航条
		 */
		function _navBar(pgCnt, /* total page count */
		url, /* get url */
		params, /* get params */
		cbf /* Call back function */) {
			$nav.find('.pgCnt').text(pgCnt);
			var $pages = $nav.find('.pages');// navBar
			$pages.empty();
			// $(elem_selector+' .pages').empty();
			for ( var i = 0; i < pgCnt; i++) {
				$pages.append('<a class="common">' + (i + 1) + '</a>');
			}
			$pages.children().eq(0).addClass("choosed");

			initFirst();
			initLast();
			initBody();
			prev();
			next();
			alterNav(0);

			function initBody() {
				$pages.children().unbind('click');
				$pages.children().click(function() {
					var idx = $(this).text();
					alterNav(idx - 1);
					getList(idx);
					return false;
				});
			}
			function initFirst() {
				$nav.find(' .firstPage').unbind('click');
				$nav.find(' .firstPage').click(function() {
					alterNav(0);
					getList('1');
					return false;
				});
			}
			function initLast() {
				$nav.find(' .lastPage').unbind('click');
				$nav.find(' .lastPage').click(function() {
					alterNav(pgCnt - 1);
					getList(pgCnt);
					return false;
				});
			}

			function prev() {
				$nav.find(' .prePage').unbind('click');
				$nav.find(' .prePage').click(function() {
					var idx = $pages.children('.choosed').text();
					if (idx == 1) {
						return;
					}
					getList(idx * 1.0 - 1);
					return false;
				});
			}

			function next() {
				$nav.find(' .nextPage').unbind('click');
				$nav.find(' .nextPage').click(function() {
					var idx = $pages.children('.choosed').text();
					if (idx == pgCnt) {
						return;
					}
					getList(idx * 1.0 + 1);
					return false;
				});
			}


			function alterNav(idx) {
				var len_v = options.navSize;
				var children = $pages.children();
				children.removeClass("choosed");
				children.css("display", "none");
				children.eq(idx).addClass("choosed");
				var s = 1.0 * idx - options.navSize / 2;
				if (s < 0)
					s = 0;
				var e = s + len_v;
				if (e > children.length)
					e = children.length;

				if (s > e - options.navSize)
					s = e - options.navSize;

				for (s; s < e; s++) {
					children.eq(s).css("display", "inline-block");
				}
				$nav.find('.pgIdx').text(idx + 1);
				// clean
				(function() {
					$nav.find(' .nextPage').removeClass('unava');
					$nav.find(' .lastPage').removeClass('unava');

					$nav.find(' .prePage').removeClass('unava');
					$nav.find(' .firstPage').removeClass('unava');
				})();

				if (idx == 0) {
					$nav.find(' .prePage').addClass('unava');
					$nav.find(' .firstPage').addClass('unava');
				}

				if (idx == pgCnt - 1) {
					$nav.find(' .nextPage').addClass('unava');
					$nav.find(' .lastPage').addClass('unava');
				}
			}

			function getList(_pgidx) {
				var paramObj = {};
				$.extend(true, paramObj, params);
				// console.log(pgLen);
				paramObj[options.IL_pg_len] = options.pgLen;
				paramObj[options.IL_pg_idx] = _pgidx;
				$.get(url, paramObj, function(json) {
					// Apply callback
					cbf(json);
					alterNav(_pgidx - 1);
					$nav.find(' .selectedPage').text(parseInt(_pgidx));
				}, 'json');
			}
			;
		}
		/**
		 * initialize body
		 */
		function _initBody() {
			if (options.allowNav)
				_renderNavBar();

			refreshData();

			return;
			

		}

		/**
		 * select td from the table
		 */
		function sel(row, col) {
			var table = table();
			if (!table)
				return;

		}
		

		// ---main rendering
		/**
		 * only called once!!
		 */
		function render() {
			if (options.allowHead)
				_initHead();
			_initBody();
			// _renderCells();
			_initFoot();
			_putTogether();
		}
		;
		

		/**
		 * Example: sel(*,0) sel(![0,1],col_id) sel([0,1,3],0) return jQueryElem
		 * Object
		 */
		function sel(row, col) {
			var _rows = _parseArgs(row);
			var _cols = _parseArgs(col);

			var ret = [];

			for ( var i = 0; i < _rows; i++) {
				var row = [];
				for ( var j = 0; i < _cols; j++) {
					row.push(_selCell(_rows[i], _cols[j]));
				}
				ret.push(row);
			}
			return ret;
		}
		/**
		 * return json
		 */
		function selData(row, col) {
			var _rows = _parseArgs(row);
			var _cols = _parseArgs(col);
			var ret = [];
			for ( var i = 0; i < _rows; i++) {
				var row = [];
				for ( var j = 0; i < _cols; j++) {
					row.push(values(_rows[i], _cols[j]));
				}
				ret.push(row);
			}
			return ret;
		}

		function _parseArgs(input) {
			var _ret = [];
			if (typeof input === 'number') {
				_ret.push(input);
			} else if (typeof input === 'string' && input === '*') {
				_ret = (function() {
					var arr = [];
					for ( var i = 0; i < list.length; i++) {
						arr.push(i);
					}
					return arr;
				})();
			} else if (typeof input === 'string' && input.startsWith("[")) {
				_ret = eval('(' + input + ')');
			} else if (typeof input === 'string' && input.startsWith("![")) {
				var not_rows = eval('(' + input.substring(1) + ')');
				_ret = (function(not) {
					var arr = [];
					for ( var i = 0; i < list.length; i++) {
						if ($.inArray(i, not))
							continue;
						arr.push(i);
					}
					return arr;
				})(not_rows);
			} else if (typeof input === 'string' && parseInt(input)) {
				_ret.push(parseInt(input));
			}
			return _ret;
		}
		
		;;
		
		function sort(sidx, sort, cb) {
			
			if( typeof(sidx) !== 'string' ){
				return false;
			}
			
			var paramObj = $.extend(true, {}, options.params);
					
					
							
			paramObj[options.IL_sort_idx] = sidx;
			paramObj[options.IL_sort_order] = sort || 'asc';
			
			if( options.url )			
			refreshData(options.url, paramObj, cb);
		}

		/*
		 * Destory -------------------------------------
		 */
		function destory() {
			this.remove();
		}
				
		/*
		 * Selection
		 * -----------------------------------------------------------------------------
		 */

		function select(idx) {

		}
		

		function unselect() { // safe to be called before renderView
			if (currentView) {
				currentView.unselect();
			}
		}
		

	}
	
	;;

})(jQuery);
;;
